package com.mashibing.tank.pojo;

import com.mashibing.tank.Strategy.DefaultFireStrategy;
import com.mashibing.tank.Strategy.FireStrategy;
import com.mashibing.tank.Strategy.FourDirFireStrategy;
import com.mashibing.tank.factory.BaseTank;

import java.awt.*;
import java.util.Random;

/**
 * @ClassName Tank
 * @Description TODO 封装属于坦克的属性和动作
 * @Author zhangjunhao
 * @DATE 2023/8/25 22:43
 */
public class Tank extends BaseTank {

    private int x, y;
    private Dir dir = Dir.DOWN;
    private static final int SPEED = Integer.parseInt((String) PropertyMgr.get("tankSpeed"));
    private boolean moving = true;
    private Random random = new Random();
    private boolean live = true;
    private static final int WIDTH = ResourceMgr.goodTankL.getWidth();
    private static final int HEIGHT = ResourceMgr.goodTankL.getHeight();
    private TankFrame tankFrame;
    private Group group = Group.BAD;
    Rectangle rectangle = new Rectangle();

    FireStrategy fireStrategy;

    public Group getGroup() {
        return group;
    }

    public int getWIDTH() {
        return WIDTH;
    }

    public int getHEIGHT() {
        return HEIGHT;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public boolean isMoving() {
        return moving;
    }

    public void setMoving(boolean moving) {
        this.moving = moving;
    }


    public void setDir(Dir dir) {
        this.dir = dir;
    }

    public Dir getDir() {
        return dir;
    }

    public TankFrame getTankFrame() {
        return tankFrame;
    }

    public Tank(int x, int y, Dir dir, Group group, TankFrame tankFrame) {
        this.x = x;
        this.y = y;
        this.dir = dir;
        this.group = group;
        this.tankFrame = tankFrame;
        rectangle.x = this.x;
        rectangle.y = this.y;
        rectangle.width = WIDTH;
        rectangle.height = HEIGHT;

        try{
            if (group == Group.GOOD) {
                String goodFSName = (String) PropertyMgr.get("goodFs");
                //记载到内存中
                fireStrategy = (FireStrategy) Class.forName(goodFSName).newInstance();
            } else {
                String badFSName = (String) PropertyMgr.get("badFs");
                fireStrategy = (FireStrategy) Class.forName(badFSName).newInstance();
            }
        } catch (IllegalAccessException | InstantiationException | ClassNotFoundException e) {
            e.printStackTrace();
        }


    }


    @Override
    public void paint(Graphics g) {

        if (!live) {
            tankFrame.getTanks().remove(this);
            return;
        }

        switch (dir) {
            case LEFT:
                g.drawImage(this.group == Group.GOOD ? ResourceMgr.goodTankL : ResourceMgr.badTankL, x, y, null);
                break;
            case RIGHT:
                g.drawImage(this.group == Group.GOOD ? ResourceMgr.goodTankR : ResourceMgr.badTankR, x, y, null);
                break;
            case UP:
                g.drawImage(this.group == Group.GOOD ? ResourceMgr.goodTankU : ResourceMgr.badTankU, x, y, null);
                break;
            case DOWN:
                g.drawImage(this.group == Group.GOOD ? ResourceMgr.goodTankD : ResourceMgr.badTankD, x, y, null);
                break;
        }

        move();
    }


    public void move() {
        if (!isMoving()) {
            return;
        }
        switch (dir) {
            case LEFT:
                x -= SPEED;
                break;
            case RIGHT:
                x += SPEED;
                break;
            case UP:
                y -= SPEED;
                break;
            case DOWN:
                y += SPEED;
                break;
            default:
                break;
        }


        //开火
        if (this.group == Group.BAD && random.nextInt(100) > 94) {
            this.fire();
        }

        //换方向
        if (this.group == Group.BAD && random.nextInt(100) > 93) {
            randomDir();
        }

        boundsCheck();

        rectangle.x = this.x;
        rectangle.y = this.y;


    }

    /**
     * @return
     * @Author zhangjunhao
     * @Description 边界检测
     * @Date 2023/8/28
     * @Param
     **/
    private void boundsCheck() {

        if (this.x < 0) {
            x = 2;
        }

        if (this.y < 28) {
            y = 28;
        }

        if (this.x > (TankFrame.GAME_WIDTH - Tank.WIDTH - 2)) {
            x = TankFrame.GAME_WIDTH - Tank.WIDTH;
        }

        if (this.y > (TankFrame.GAME_HEIGHT - Tank.HEIGHT - 2)) {
            y = TankFrame.GAME_HEIGHT - Tank.HEIGHT - 2;
        }


    }

    /**
     * @return
     * @Author zhangjunhao
     * @Description 随机换衣方向
     * @Date 2023/8/28
     * @Param
     **/
    private void randomDir() {
        this.dir = Dir.values()[random.nextInt(4)];
    }



    /**
     * @return
     * @Author zhangjunhao
     * @Description 坦克开火模式(动作) 策略模式
     * 能用传参数就传参数,因为成员变量的作用域是整个类,传参数是方法体内有效
     * 会导致类的结构变复杂
     * 传参数的坏处:每次调用需要new一个,所以可以把传参数的类,变成单例模式
     **/
    FireStrategy fireStrategy1 = new DefaultFireStrategy();

    public void fire() {
        fireStrategy.fire(this);
    }


    FireStrategy fireStrategy2 = new FourDirFireStrategy();

    public void fire1() {
        fireStrategy2.fire(this);
    }


    /**
     * @return
     * @Author zhangjunhao
     * @Description 坦克与子弹相撞之后消失
     * @Date 2023/8/28
     * @Param
     **/
    public void die() {
        this.live = false;
    }
}
